#pragma once

#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <string>
#include <functional>

using namespace std;

template <class T>
using func_t = function<void(T)>;

template <class T>
class Thread
{
public:
    Thread(func_t<T> func, T data, const string name = "None")
        : _func(func),
          _name(name),
          _data(data)
    {
    }
    static void *thread_run(void *arg)
    {
        Thread *self = static_cast<Thread *>(arg);
        self->_func(self->_data);
        return nullptr;
    }
    bool start()
    {
        int ret = pthread_create(&_tid, nullptr, thread_run, this);
        return ret == 0;
    }
    void detach()
    {
        pthread_detach(_tid);
    }
    void join()
    {
        pthread_join(_tid, nullptr);
    }
    string name()
    {
        return _name;
    }

private:
    pthread_t _tid;
    string _name;
    func_t<T> _func;
    T _data;
};